#include "head.h"

//客户端接收文件函数
//第一个参数：客户端和服务端网络通信的socket对象fd
//第二个参数：gets命令后文件名的绝对路径            
int recvFile(int socket_fd,transport_protocol_t *msg){

    // 接收hash值前，先接收用户发送的文件是否存在标记
    int is_file = 0;
    recv(socket_fd, &is_file, sizeof(int), MSG_WAITALL);
    if (is_file != 0)
    {
        printf("没有此文件,gets命令执行结束!\n");
        return 0;
    }
    
    int file_fd = open(msg->buf, O_RDWR|O_CREAT|O_APPEND, 0600);

    //获取文件大小
    struct stat st;
    memset(&st,0,sizeof(st));
    fstat(file_fd,&st);
    
    //接受文件前把已下载的文件大小发送给服务端
    off_t updated_size = st.st_size;
    printf("已下载的文件大小:%ld\n",updated_size);
    send(socket_fd,&updated_size,sizeof(off_t),MSG_NOSIGNAL);

    // 接收文件大小
    off_t file_size = 0;
    recv(socket_fd, &file_size, sizeof(off_t), MSG_WAITALL);
    //printf("client: file_size: %ld \n", file_size);
    
    //已有部分下载好的文件,还要接受的文件大小肯定小于源文件大小
    if(updated_size != 0){
        off_t updated_num = updated_size / 4096;
        //调整文件大小为源文件大小
        ftruncate(file_fd,file_size+updated_num*4096);
        // 接收数据
        printf("%ld\n",updated_num*4096);
        void *p = mmap(NULL, file_size, PROT_READ|PROT_WRITE,
                        MAP_SHARED, file_fd, updated_num*4096);
        //printf("recv before %ld\n",file_size);
        //TODO：socket_fd断开连接
        int recv_size = recv(socket_fd, p, file_size, MSG_WAITALL);
        //printf("recv_size2:%d\n",recv_size);
        //ERROR_CHECK(recv_size,-1,"recv");
        printf("接受完毕\n");
        //切割文件大小为recv接受的大小+已接收的完整页大小
        ftruncate(file_fd,recv_size+updated_num*4096);   
        munmap(p, file_size);
        close(file_fd);
        return 0;
    }
    //已下载文件大小为0
    // 首先在mmap之前调整文件大小, 让文件足够大
    ftruncate(file_fd, file_size);

    // 接收数据
    void *p = mmap(NULL, file_size, PROT_READ|PROT_WRITE, MAP_SHARED, file_fd, 0);
    //printf("recv before\n");
    int recv_size = recv(socket_fd, p, file_size, MSG_WAITALL);
    //printf("recv_size:%d\n",recv_size);
    //ERROR_CHECK(recv_size,-1,"recv");
    printf("接受完毕\n");
    //切割文件大小为recv接受的大小
    ftruncate(file_fd,recv_size);

    munmap(p, file_size);

    close(file_fd);
    return 0;
}





